Cross-domain download pictures go on all sorts of detours and difficulties encountered

Source: Internet
Author: User
Tags sorts

First of all, I am programming rookie, just do programming soon. Welcome to shoot Bricks

features to implement :

We have a travel website (North-South tour), can publish travel notes. Rich Text, write Raiders, upload pictures (we will be cut into the image of large and medium-sized pictures, convenient for different places to call).

However, one situation is that users will copy and paste the articles they posted on other websites to our website, and the result is that we save only the link address of the picture, and not actually save the picture. When you use this image elsewhere, you will see an inappropriate image size or a wall chart.

The solution is to download the image to our server based on the user's pasted address. Then change the address of the other website in the text box to the address of your website and save it. It took a bit of a while to implement this function.

the first way to try:

using jquery to traverse the pictures in the rich text box before saving, we find that the images of our website are sent to the background processing, and the asynchronous commit uses $.post.

Probably one of the code

$ ("#kecontent >img"). each ({            var src = $ (this). attr ("src");            if (Src.indexof ("nanbeiyou.com") <=0) {                $.post ("http://file.nanbeiyou.com/******&remotepath=" + encodeURI (SRC),                success:function () {                  //do some thing                });}                         );

  

Background based on the address passed, the simulation browser to save the picture to the content, and then cut to save to the server. (soon realized, found to download the picture saved to the server, really happy, thought that almost finished it)

Correction 1

soon discovered the problem, the program under the www.nanbeiyou.com domain, and the downloaded picture under the file.nanbeiyou.com resource domain, $.post cannot cross the domain to obtain the returned picture name. The person in charge said to use IFRAME cross-domain to get it.

I think of jquery's Jsonp way to cross-domain, online check: http://www.cnblogs.com/know/archive/2011/10/09/2204005.html, and then use $.ajax JSONP to make asynchronous requests.

Debug found using Jsonp can actually return the name of the picture (plus the fixed address on the front OK), but when the number of pictures sent, how to the name of the picture and its original address, replace the original other website address it? So before sending the picture's original address, give the picture tag attribute a unique number (using index is appropriate, no more random number), and then send the picture source address and index number together to the background, the background processing the picture, the picture name and the index back again, The address is replaced by the IMG in the returned index match page. It's a good idea to realize it.

Front page code:

$ ("#kecon >img"). each (function (index) {var src = $ (th            IS). attr ("src");            $ (this). attr ("random", index);                  if (Src.indexof ("nanbeiyou.com") <=0) {$.ajax ({type: "Get", Async:true,                  URL: "http://file.nanbeiyou.com/*****&remotepath=" +encodeuri (SRC) + "&random=" +index,                  DataType: "Jsonp", Jsonp: "Callbackparam",//passed to the request handler or page, to obtain the name of the JSONP callback function name (default: Callback) Jsonpcallback: "Success_jsonpcallback",//Custom JSONP callback function name, default to jquery automatically generated random function name Success:function (JSON)                                    {$ ("#kecon >img[random= '" +json[0].random+ ""] "). attr (" src ") =json[0].name;                 }, Error:function () {alert (' fail ');            }                                }); }         });

Adding a property named "Random" to later found that it might be a jquery reserved word that would change the random to Rands.

Stupid low-level mistakes always have:

$ ("#kecon >img[rands= '" +json[0].rands+ ""] "). attr (" src ") =json[0].name; should be changed into
$ ("#kecon >img[rands= '" +json[0].rands+ ""] "). attr (" src ", json[0].name);

Backstage implementation: This is from the Internet to find, colleagues gave me, I do not know the source.

<summary>/////Based on the image URL entered, download the image into memory///</summary>//<param name= "Downaddress" >        </param>//<returns></returns> private static MemoryStream DownLoad (String downaddress)            {MemoryStream ms = new MemoryStream ();            HttpWebRequest request = (HttpWebRequest) httpwebrequest.create (downaddress); Request.            AllowAutoRedirect = false; Request.            Method = "GET"; Request. useragent = "opera/9.25 (Windows NT 6.0; U                        EN) "; HttpWebResponse response = (HttpWebResponse) request.            GetResponse (); Stream Responsestream = Response.            GetResponseStream ();            int i;            byte[] buffer = new byte[2048];            Delsetprocess Pro = new Delsetprocess (setprocess);                do {i = responsestream.read (buffer, 0, 2048); Ms.                Write (buffer, 0, I); This.            Invoke (PRO);          }  while (i > 0); Response.            Close ();            Responsestream.close ();            Responsestream.dispose ();            Response = NULL;            request = NULL;            Responsestream = null;        return MS; }

Save the picture in the background, call download.

if (context. request.params["Pictype"] = = "Travel" && context. request.params["RemotePath"] = null) {string OldPath = context.                    request.params["RemotePath"];                    String oldname = oldpath.substring (Oldpath.lastindexof ('/') +1);                    String oldext = oldpath.substring (Oldpath.lastindexof ('. ')); int index = Int. Parse (context.                    request.params["random"]);                   MemoryStream ms = DownLoad (OldPath);                                        Set a random number name string newName = Photoinfo.generatid () to the local picture.                                                using (photoinfochain pi = thumbfactory.getinstancephotoinfochain ("Travel")) { Pi.                        Stream = ms; According to the name, the picture is cut into large and small pictures to save to the local server pi. Save (NewName);
Newext = pi.infolist[0]. Imgformat; Context. Response.ContentType = "Text/plain"; String callbackfunname = context. request["Callbackparam"]; Context. Response.Write (Callbackfunname + "([{name:\" "+newname + newext+" \ ", rands:\" "+index+" \ "}]"); }; }

  Correction 2

Using the jquery method above, when two pictures are pasted into the text box, opening the browser debugging to view the network information, is sending two JSONP asynchronous requests in the back, each request successfully returned to obtain the new name of the picture and index (0 and 1), but $.ajax () The JSON obtained in the success method can be obtained two times, but two times of json[0].rands are 1, or 0. Not two. I don't know what the reason is. Which Master has encountered, to explain.

There is the use of asynchronous, will be sent out of multiple requests, do not know what time the picture is downloaded to complete, address replacement is complete, when the entire travel form submitted to save. So give up a picture address a JSONP request. Instead, the page text box is first traversed, and all the image addresses that need to be replaced are placed in a string variable separated by commas. Once an asynchronous request all the picture address sent to the background code, and then the background code to send the picture address of the string object resolution delimited, the picture download for each address, and then the picture of the new name and the original address of the picture (the address in front of the page to match, so that the new value replacement) into the JSON returned.

Improvement 3

Try to paste the above method 10 pictures, you can successfully save the travels, the process is a bit slow, but can be successful, so in the click to save the travel notes at the same time pop up a little hint "travels are saved, please later." "The principle is simple, there is a hidden div, click on save, the hint div display."

Improvement 4

After using the improvement 3, a number of pictures are saved, but also to the user a reminder, the original thought this is OK. Did not expect to find the problem, when pasting a lot of pictures, such as 50 pictures, save is unsuccessful, has been prompted to save, nor error, sent to the JSONP request no echo, no view browser network information, it is sent time after the time is too long, timed out, so unsuccessful. Check Baidu, Google. $.ajax does have a timeout parameter, which is more the reason for timeout. So after setting the timeout parameter to $.ajax, the save fails, and there are no reminders. Thought to save the failure to fail, how to give a hint to tell me that failed, do not let me wait, set the error function how not to trigger it?

Another one. Check: http://stackoverflow.com/questions/1002367/jquery-ajax-jsonp-ignores-a-timeout-and-doesnt-fire-the-error-event

originally for $.ajax requests in JSONP format, the error method cannot be triggered until the jquery1.5 version . we use the jquery1.4, why it is so inch. It looks good. There is a plugin Jquery.jsonp solves this problem, well then use the Jquery.jsonp method to rewrite it again. Jquery.jsonp api:https://github.com/jaubourg/jquery-jsonp/blob/master/doc/api.md.

This default callback function is named: "_jqjsp". After the rewrite is done, the timeout error can be detected when the timeout is set short. Thought this assembly, set the timeout a little longer, paste more than 40 pictures at a time, click Save. Error errors, not timeout errors. What is the reason for this? Check out some browser network monitoring. HTTP 400 error, url too long. The original use of $.ajax when the save failed also did not error, is not the URL too long reason? URL too long can be submitted with post, try a $.ajax JSONP format submission can only use "get", can not be submitted with "post". All the work done was done in vain, and everything was zeroed out.

Use the IFRAME to submit, the IFRAME can be used post submission, so that the number of submissions is not limited.

Background picture Saver instead of multi-threaded save. Put the picture that needs to be downloaded into a dictionary{picpath, ' wait '}. Use for loop traversal to download each picture. Because of the use of multi-threading, the lock is made when a thread determines whether the picture is downloaded in dictionary. Modify the status of the picture "waiting" to ' downloading '. Then release the lock. Other threads can judge, if the status is "downloading", continue, loop to determine whether the next picture is downloaded. For the picture to save the separation of the class pi, because of multi-thread sharing, will cause a picture has not been downloaded to save, there is a new picture added, resulting in the download of the picture is not complete. So put this shared class in each thread and separate (instantiate) one for each thread. When a child thread is saved, the physical path is judged by its relative path: the Httpcontent.current.server.mappath () method is used, and the httpcontent.current in the child thread is null. Later, when passing parameters, the physical address is transmitted directly, but relative to the address.  This conversion can be done in the main thread. If the user to Rich text paste on both sides of the duplicate picture, will cause the key value in the dictionary duplicate, with the page the day before yesterday to determine whether there are duplicate image address, if there is only one copy in the source into the background. When two duplicate picture addresses are passed, when the return is replaced, if only replace, only one is replaced, and the second matches the condition without substitution. Using regular expressions can solve this problem.

Background download save may appear exception, catch exception, and then return the picture name "Nanbeiyou", other received feedback to judge, if it is "nanbeiyou" know that the picture download failed, do not replace the image address.

The day before yesterday to pass the post without the number of pictures limit, but in the background to jump the length of the URL is limited, with the rich text in the foreground to judge the number of pictures, every 90 back to the table, return callback, and then callback to determine the number of outstanding images, if 0, the entire form is submitted, If it is more than 90, then pass 90, between 0 and 90, then the rest is passed.

Later found that some sites on the image URL is very special: QQ space as an example: Http://user.qzone.qq.com/307722709/blog/1341022967#!app=2&via=QZ. An image address in the hashrefresh&pos=1340365654:

http://b206.photo.store.qq.com/http_imgload.cgi?/rurl4_b= 809f8ca26fba5d947e8642f699ec5571421e5e9c7e38a6cbfdf982c0696537766a8ab54a8f9302ed2743d23408c344b9e9dfeea2928c4f3e0b25cb74c 9ebb0da168db30206c32443959287af61818a8321d7dbf5&a=206&b=206

1, the picture address does not have the picture suffix name, through the URL analysis cannot get the picture type. So after passing the Reque request, get

HttpWebResponse response = (HttpWebResponse) request. GetResponse ()
After that, the type of the picture can be obtained by Response.ContentType, thus obtaining the suffix name.

2. After the address & paste into the rich text box, the corresponding hidden field tcontent &amp; so need to make a regular match to the URL will be so & replace &amp;

3, some image address download need to jump similar to MVC, so will download () in the

Request. AllowAutoRedirect = false; This sentence is removed.

4. Is there one in the URL? , in the regular it is a regular match that matches, so need to be in the URL?  Switch to \? In order to match to the correct URL



4.

//$.ajax ({
//Type: "Get",
//timeout:10000,
//Async:true,
//URL: "@ (FilePath)/upload.upx?random=" + Math.random () + "&pictype=travel&remotepath=" +encodeuri (sources),
//DataType: "Jsonp",
//JSONP: " Callbackparam ",//pass to the request handler or page to obtain the parameter name of the JSONP callback function name (default: Callback)
//Jsonpcallback:" Success_jsonpcallback ",// Custom JSONP callback function name, default jquery automatically generated random function name
//success:function (JSON) {
//$ ("#Cover"). Val (Json[0].newpath);
for (Var i=0;i<json.length;i++) {
////$ ("#kecontext >img[src= '" +json[i].oldpath+ "]"). attr ("src", $ ("# Imgpath "). Val () +json[i].newpath);
//if ($ ("#imgTitle"). val () = = "") {
//$ ("#imgTitle"). Val (Json[i].newpath);
}
//else {
//$ ("#imgTitle"). Val ($ ("#imgTitle"). Val () + ";" + Json[i].newpath);
}
//$ ("#Tcontent"). Val ($ ("#Tcontent"). Val (). Replace (json[i].oldpath,$ ("#imgpath"). Val () +json[i].newpath)) ;

//
//}
//
//$ ("#form"). Submit ();

//},
//Error:function (x,t,m) {
//if (t=== "timeout")
//{
//alert ("You have uploaded too many pictures, save failed!") ");
//}else{
//Alert ("t=" +t);
Alert ("m=" +m);
//Alert ("x=" +x);
//}
//
//}
//});
//$.jsonp ({
//Type: "POST",
//URL: "@ (FilePath)/upload.upx?random=" +math.random () + "&pictype=travel &remotepath= "+encodeuri (sources) +" &callback=? ",
//timeout:120000,
//Context:sources,
//// Callbackparameter: "Callbackparam=success_jsonpcallback",
//Success:function (json,textstatus) {
//$ ("# Cover "). Val (Json[0].newpath);
//for (Var i=0;i<json.length;i++) {
//
//if ($ ("#imgTitle"). val () = = "") {
//$ ("#imgTitle"). Val (json[ I].newpath);
//}
//else {
//$ ("#imgTitle"). Val ($ ("#imgTitle"). Val () + ";" + Json[i].newpath);
}
//$ ("#Tcontent"). Val ($ ("#Tcontent"). Val (). Replace (json[i].oldpath,$ ("#imgpath"). Val () +json[i].newpath)) ;

//
// }
$ ("#form"). Submit ();
//
// },
Error:function (Xoptions, Textstatus) {
if (textstatus=== "timeout") {
Alert ("Travel Notes save Timeout");
// }
else{
Alert ("An error has occurred! ");
// }
//
// }
//
// });

String returnval = "[";
String returnval = "";

foreach (string path in arr)
{
string oldpath = path;
String oldname = oldpath.substring (Oldpath.lastindexof ('/') + 1);
String oldext = oldpath.substring (Oldpath.lastindexof ('. '));
MemoryStream ms = DownLoad (OldPath);

String newName = Photoinfo.generatid ();
String newext = "";
func<string, string> _func = x = x;

using (photoinfochain pi = thumbfactory.getinstancephotoinfochain ("Travel"))
{
Pi. Func = _func;
Pi. Filename = Oldname;
Pi. Stream = ms;

Pi. Save (NewName);
Ms. Dispose ();
Newext = pi.infolist[0]. Imgformat;
ReturnVal + = "{oldpath:\" "+ OldPath +" \ "+", "+" NewPath: "+" \ "" + newName + newext+ "\"}, ";
ReturnVal + = NewName + Newext + ":";
}
}
ReturnVal = returnval.substring (0, returnval.length-1);
ReturnVal + = "]";

String callbackfunname = context. request["Callbackparam"];
Context. Response.Write (Callbackfunname + "(" + ReturnVal + ")");
Context. Response.Write ("_jqjsp" + "(" + ReturnVal + ")");

Cross-domain download pictures go on all sorts of detours and difficulties encountered

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.