项目二(业务GO)——跨域上传图片(请求接口)

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

问题来源:

何为“跨域”? ——就是给你一个接口,外面暴露的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.这次需求改动总结的小经验:

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

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值