之前,就听过“跨域上传”图片的问题,只是疏于研究,也就一再搁置,直至今天再次遇见这个不能避免的“坑”,才不得不思考一下,怎么“跨域上传”图片或者文件?

问题来源:

何为“跨域”? ——就是给你一个接口,外面暴露的url(并非是自己项目中的url),然后你发post()请求,请求给你的接口,请求成功,接口就会返回给你想要的结果。

实际情况:

我们公司自己做的项目一般都是使用nodejs的thinkjs框架(ThinkJS 是一款使用 ES6/7 特性全新开发的 Node.js MVC 框架,使用 ES7 中 async/await,或者 ES6 中的 */yield 特性彻底解决了 Node.js 中异步嵌套的问题。)之前我们的上传图片都是显示在自己项目本地,而这次的需求却加上了请求另一个人的接口地址,然后正常上传图片。

页面HTML主要代码:

...
<label style="fmargin-top: 10px;width: 100px" ></label>
<div id="addImg">
<span class="addImglist"></span>
<img id="addPic" style="float: left;margin-top: 20px;margin-left: 20px" width="150px" height="100" src="/static/admin/img/addimg.jpg" onclick="addImg()">
</div>
<input type="file" name="uploadFile" id="fileupload_input" style="display: none"/> <div class="temp" style="float: left;margin-top: 20px;margin-left: 20px">
<img src="" class="showImg" ondblclick="canceImg(this)" width="150px" height="100"/>
<input type="hidden" class="imgs" name="imgs"/>
</div>
...
<script>
function addImg() {
uploadimg('dynamic');
} function uploadimg(type) {//这里的图片上传分为两种形式:动态以及用户头像
var url='';
if(type=='dynamic'){
url="/tools/uploadutils/uploadtonet?type=dynamic&t=" + new Date().getTime();//文件上传地址 请求接口地址
}else{
url="/article/article/upload?type=portrait&t=" + new Date().getTime();//文件上传地址
}
jQuery('#fileupload_input').click().fileupload({
dataType: 'json',
url: url,
done: function (e, result) {
if (result.result.errno==0) {
var data=result.result.data;
if(type=='dynamic'){
jQuery(".temp:first").clone().appendTo('#addImg .addImglist');
if(jQuery(".temp").length>=10){
jQuery("#addPic").hide();
}
jQuery('#addImg .showImg:last').attr("src",data.path);
jQuery('#addImg .imgs:last').val(data.savePath);
}else{
jQuery('#portrait').attr("src",imgsite+"/static"+data.path);
jQuery('#img').val(data.savePath)
}
} else {
jQuery.messager.alert('提示', "上传失败");
}
}
});
} function canceImg(me) {
jQuery(me).parent().remove();
if(jQuery(".temp").length<10){ //只能上传九张图
jQuery("#addPic").show();
}
}
</script>

后台项目中的js代码:

uploadutils.js(文件路径:/tools/uploadutils/的uploadtonet方法):

/**
* Created by *** on 2016/11/10
*/
'use strict'; import Base from '../base.js';
import imgutil from '../../../common/util/imgutil';
import fs from 'fs';
import request from 'request'; export default class extends Base {
/**
* 上传图片给前台接口(c#程序)
* @returns {Promise|*|void|PreventPromise}
*/
async uploadtonetAction() {
let type = this.get("type");
if (!think.isEmpty(this.file('uploadFile'))) {
let savePath = "";//保存在数据库的路径
let file = think.extend({}, this.file('uploadFile'));
let fPath = file.path;
let suffix = fPath.substr(fPath.lastIndexOf(".") + 1);
if (suffix == "jpg" || suffix == "png" || suffix == "jpeg") {
let apiBaseUrl = this.config("apiUrl");
let reqUrl = apiBaseUrl + "/upload.ashx"; //c#接口请求地址
let fileObj = imgutil.getCSharpImageUrl(this.param("type"), suffix);
let path = fileObj.path + fileObj.fileName;
let dbUri = "/" + path; //数据库保存的路径
let req = think.promisify(request.post);
let options = {
url: reqUrl,
method: "post",
formData: {
file: fs.createReadStream(fPath),
path: path
}
};
let res = await req(options);
let result = JSON.parse(res.body);
let imgUrl = this.config("apiImgsite") + dbUri; //回显的路径
if (result.status == 1) {//上传成功
savePath = result.data.join(',');
return this.success({
path: imgUrl,
savePath: savePath
});
} else {
return this.fail();
}
} else {
return this.fail("上传图片格式有误,请重新上传!");
}
}
} //跨域请求的方法
call = async function (url, fPath, path) {
let req = think.promisify(request.post);
let reqObj = {
url: url,
method: "post",
formData: {
file: fs.createReadStream(fPath),
path: path
}
};
return req(reqObj);
};
}

主要的问题出在哪里呢???其实主要知识点就是在下:

这段代码是老大给的,为此还被骂了一顿(这段代码很难理解吗?其实也不然,有时候就是觉得自己的脑子在代码运行方面实在不怎么灵光!明明自己知道的东西,因为粗心或者不自信总是犯错,导致一些不可挽回的“形象破坏”):

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单".比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件。(https://developer.mozilla.org/zh-CN/docs/Web/API/FormData)

在网上找到了一个C#实现http协议GET、POST请求 ,觉得挺好的    http://blog.chinaunix.net/uid-7552018-id-173395.html

const options = {
method: 'POST',
uri: testData.url + `uploadprofilephoto`,
formData: {
image: fs.createReadStream('/home/rje/photo.jpg')
}
};
const json: IResponse<string> = await request(options);

uri:就是要请求的图片上传地址;

formData:模拟表单提交,接口需要两个参数,一个文件路径,一个文件名,以键值对的形式传给它,最终便会返回给你想要的东西了。

只是在此项目中,使用await request(option)得不到接口返回的结果,于是只能使用thinkjs自带的 think.promisify()   —— think.promisify将一个异步函数自动改造,返回一个promise对象以供调用。

1.npm中request-promise模块(https://www.npmjs.com/package/request-promise),有具体的用法;

2.这次需求改动总结的小经验:

点击“添加图片”的时候,自动往后面添加一个相同的上传图片的点击框,即:

自己写的代码总是冗杂繁余,而其他人写的代码一看却是那么的简洁明了,不得不怀疑自己的能力。而自己想长期快乐的继续自己的这份工作时,就应该好好的沉淀自己,把自己培养成像同事一样的大神。

项目二(业务GO)——跨域上传图片(请求接口)的更多相关文章

  1. vue.js axios实现跨域http请求接口

    跨域post实例,用到了qs组件来避开ajax信使请求,并兼容Android. import axios from 'axios'; import qs from 'qs'; axios.post(' ...

  2. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十二 || 三种跨域方式比较,DTOs(数据传输对象)初探

    更新反馈 1.博友@落幕残情童鞋说到了,Nginx反向代理实现跨域,因为我目前还没有使用到,给忽略了,这次记录下,为下次补充.此坑已填 2.提示:跨域的姊妹篇——<三十三║ ⅖ 种方法实现完美跨 ...

  3. kindeditor4跨域上传图片解决

    项目中正在使用kindeditor, 版本号4.1.10 非常多公司的图片会走CDN,须要单独的一台图片上传服务如:(upload.268xue.com) kindeditor上传图片的简单内部流程: ...

  4. 跨域Ajax请求WebService方法

    一.允许跨域Ajax请求,更改如下配置: 在要调用的WebService上面添加特性标签: 二.以如下返回用户信息的WebService方法为例 三.在另一个网站上通过Ajax访问webService ...

  5. 【笔记】vue-cli 开发环境中跨域连接后台api(vue-resource 跨域post 请求)

    在vue-cli 项目中很多人会用到mock 数据(模拟数据),但是我觉得如果在真实的数据库交互中开发会更有安全感一些,所以查了一下百度很多人推荐的就是: 跨域! 跨域是什么概念?不同的主机名,同主机 ...

  6. ueditor富文本编辑器跨域上传图片解决办法

    在使用百度富文本编辑器上传图片的过程中,如果是有一台单独的图片服务器就需要将上传的图片放到图片服务器,比如在a.com的编辑器中上传图片,图片要保存到img.com,这就涉及到跨域上传图片,而在ued ...

  7. 【HTTP header】【Access-Control-Allow-Credentials】跨域Ajax请求时是否带Cookie的设置

    1. 无关Cookie跨域Ajax请求 客户端 以 Jquery 的 ajax 为例: $.ajax({ url : 'http://remote.domain.com/corsrequest', d ...

  8. 原创:【ajax | axios跨域简单请求+复杂请求】自定义header头Token请求Laravel5后台【亲测可用】

    如标题:我想在ajax的header头增加自定义Token进行跨域api认证并调用,api使用laravel5编写,如何实现? 首先,了解下CORS简单请求和复杂请求.  -- CORS简单请求 -- ...

  9. 跨域Ajax请求时是否带Cookie的设置

    1. 无关Cookie跨域Ajax请求 客户端 以 Jquery 的 ajax 为例: $.ajax({ url : 'http://remote.domain.com/corsrequest', d ...

随机推荐

  1. 注解的基本盘点 -- 《Java编程思想》

    注解(元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在之后的某一个时刻非常方便地使用这些数据. ---<Java编程思想> 其实注解可以理解为一个工具类,只要使用了这个工 ...

  2. 完全偶图K(3,3)与完全图K5是否存在平面表示

    本文论述k(3, 3)与K5平面表示的存在性.首先给出图的平面表示的定义: 若可以在平面里画出一个图而让边没有任何交叉(边的交叉是指边的直线或弧线在它们的公共端点以外的地方相交),则这个图是平面性的. ...

  3. 什么是JSP?它有哪些特点?

    什么是JSP? 它有哪些特点?  JSP是服务器端的一种基于java语言的网页技术,它是由一些JSP标记,java程序段以及HTML文件组成的结合体,以java语言作为其内置的脚本语言.  实质上是通 ...

  4. jsp中用EL读取了数据库里面的时间,怎么设置格式显示的格式

    首先导入标签 <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> < ...

  5. 数据库中 关于不能用in 不能用exist 等关键字 查询不出现字段的问题

    这是之前在网上见到的一道题,后来心里略微想了想 觉得应该可能,所以就一闪而过了,之前去面试晨光的时候面试者问了我这道问题,当时也只是把自己的想法说了一下,可能因为当时面试的感觉不太好,面试官也没有追究 ...

  6. python学习笔记系列----(二)控制流

    实际开始看这一章节的时候,觉得都不想看了,因为每种语言都会有控制流,感觉好像我不看就会了似的.快速预览的时候,发现了原来还包含了对函数定义的一些描述,重点讲了3种函数形参的定义方法,章节的最后讲述了P ...

  7. Java 可变参数列表

    1.可变参数列表的简单实现 当调用方法时,方法的参数个数或类型未知时,称其为可变参数列表.在以前的Java代码中,可以使用Object数组来实现这样的功能.因为,所有的类都是直接或间接继承于Objec ...

  8. Scala入门学习笔记三--数组使用

    前言 本篇主要讲Scala的Array.BufferArray.List,更多教程请参考:Scala教程 本篇知识点概括 若长度固定则使用Array,若长度可能有 变化则使用ArrayBuffer 提 ...

  9. Ugly Number II

    注意负数,所以要使用long,而不能用int 详细解释 请参见http://www.cnblogs.com/julie-yang/p/5147460.html #include<vector&g ...

  10. Dynamics AX 2012 R3 Demo 安装与配置 - 编译和配置 (Step 3)

        在前两节中,Reinhard主要讲解了如何配置安装环境,安装数据库服务器,AOS和客户端.至此安装工作已经结束,下面Reinhard开始讲解如何编译和配置.     运行客户端后,系统弹出初始 ...